package cn.felord.verse.configure;

import cn.felord.common.http.Rest;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.Objects;

import static org.springframework.web.util.WebUtils.*;

@Slf4j
@RestController
@RequestMapping("${server.error.path:${error.path:/error}}")
public class DefaultErrorController extends AbstractErrorController {

    /**
     * Instantiates a new Default error controller.
     *
     * @param errorAttributes the error attributes
     */
    public DefaultErrorController(ErrorAttributes errorAttributes) {
        super(errorAttributes);
    }

    /**
     * 其它Servlet等Spring MVC 捕捉不到时会被 /error 捕捉
     *
     * @param request the request
     * @return the rest
     * @throws Exception the exception
     */
    @RequestMapping
    public Rest<?> error(HttpServletRequest request) throws Exception {
        Object uri = request.getAttribute(ERROR_REQUEST_URI_ATTRIBUTE);
        Exception exception = (Exception) request.getAttribute(ERROR_EXCEPTION_ATTRIBUTE);
        Object exceptionType = request.getAttribute(ERROR_EXCEPTION_TYPE_ATTRIBUTE);
        String message = (String) request.getAttribute(ERROR_MESSAGE_ATTRIBUTE);
        String msg = String.format("uri: %s exception-type: %s exception: %s", uri, exceptionType, message);
        Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        if (Objects.equals(HttpStatus.NOT_FOUND.value(),statusCode)){
            throw new NoHandlerFoundException("Not Found",uri.toString(), HttpHeaders.EMPTY);
        }
        if (exception!=null){
            throw exception;
        }
        throw new Exception(msg);
    }
}
